package com.levi.pay.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.levi.constants.MallConstants;
import com.levi.pay.enums.PayPlatformEnum;
import com.levi.pojo.PayInfo;
import com.levi.pay.service.PayInfoService;
import com.levi.pay.service.PayService;
import com.lly835.bestpay.enums.BestPayPlatformEnum;
import com.lly835.bestpay.enums.BestPayTypeEnum;
import com.lly835.bestpay.enums.OrderStatusEnum;
import com.lly835.bestpay.model.PayRequest;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.service.BestPayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * @author shentong
 * @since 2022/3/16 8:05 PM
 */
@Service
@Slf4j
public class PayServiceImpl implements PayService {
    @Autowired
    private PayInfoService payInfoService;

    @Value("${imooc.uid}")
    String uid;

    @Autowired
    private BestPayService bestPayService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayResponse create(String orderId, BigDecimal amount, BestPayTypeEnum bestPayTypeEnum) {
        //创建订单，插入数据库
        PayInfo payInfo = new PayInfo(Long.parseLong(orderId), PayPlatformEnum.getPayPlatformStatus(bestPayTypeEnum), OrderStatusEnum.NOTPAY.name(),amount);
        payInfoService.save(payInfo);
        //创建支付订单
        PayRequest payRequest = new PayRequest();
        payRequest.setPayTypeEnum(bestPayTypeEnum);
        payRequest.setOrderId(orderId);
        payRequest.setOrderName(uid + "-" + "测试订单");
        payRequest.setOrderAmount(amount.doubleValue());
        //bestPayService对象里面放的有微信和支付宝的配置
        PayResponse payResponse = bestPayService.pay(payRequest);
        //payResponse中包含支付的连接(codeUrl)，放到二维码中，用户扫码支付，支付之后微信会异步通知到回调地址url
        log.info("创建支付订单response=>{}", payResponse);
        return payResponse;
    }

    @Override
    public String asyncNotify(String notifyData) {
        //验证签名
        PayResponse payResponse = bestPayService.asyncNotify(notifyData);
        log.info("异步通知response=>{}",payResponse);

        //查询数据库订单验证金额是否一致
        LambdaQueryWrapper<PayInfo> ew = new LambdaQueryWrapper<>();
        ew.eq(PayInfo::getOrderNo, payResponse.getOrderId());
        PayInfo payInfo = payInfoService.getOne(ew);
        if (payInfo == null) {
            //可通过钉钉，邮箱报警通知
            throw new RuntimeException("订单不存在！orderId="+ payResponse.getOrderId());
        }
        if (!Objects.equals(payInfo.getPlatformStatus(), OrderStatusEnum.SUCCESS.name())) {
            if (payInfo.getPayAmount().compareTo(BigDecimal.valueOf(payResponse.getOrderAmount())) != 0) {
                throw new RuntimeException("支付金额与订单金额不一致！");
            }
            //修改订单状态
            payInfo.setPlatformStatus(OrderStatusEnum.SUCCESS.name());
            payInfo.setPlatformNumber(payResponse.getOutTradeNo());
            payInfoService.updateById(payInfo);
        }
        //TODO 发送消息到MQ  通知订单修改状态为已付款
        amqpTemplate.convertAndSend(MallConstants.PAY_MSG_QUEUE,new Gson().toJson(payInfo));
        //如果以上全部校验通过，就返回以下内容，告诉微信不用再继续通知了，微信返回xml，支付宝返回success
        BestPayPlatformEnum payPlatformEnum = payResponse.getPayPlatformEnum();
        if (Objects.equals(payPlatformEnum, BestPayPlatformEnum.WX)) {
            return MallConstants.WX_SUCCESS;
        }else if (Objects.equals(payPlatformEnum,BestPayPlatformEnum.ALIPAY)){
            return MallConstants.ALI_SUCCESS;
        }
        throw new RuntimeException("支付平台信息有误！");
    }


    @Override
    public PayInfo getPayInfoByOrderId(String orderId) {
        LambdaQueryWrapper<PayInfo> ew = new LambdaQueryWrapper<>();
        ew.eq(PayInfo::getOrderNo, orderId);
        return payInfoService.getOne(ew);
    }
}
